package com.baitai.system.service.impl;

import java.beans.Transient;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.baitai.common.core.domain.AjaxResult;
import com.baitai.common.core.domain.R;
import com.baitai.common.core.domain.entity.SysUser;
import com.baitai.common.utils.CommonUtils;
import com.baitai.common.utils.DateUtils;
import com.baitai.common.utils.StringUtils;
import com.baitai.system.domain.*;
import com.baitai.system.domain.vo.PrizeDrawRuleVo;
import com.baitai.system.domain.vo.PrizeProductInfo;
import com.baitai.system.mapper.*;
import com.baitai.system.service.ISysUserService;
import com.baitai.system.service.IUserPointsLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baitai.system.service.IPrizeDrawRuleService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 抽奖规则Service业务层处理
 *
 * @author ruoyi
 * @date 2024-07-11
 */
@Service
public class PrizeDrawRuleServiceImpl implements IPrizeDrawRuleService {
    @Autowired
    private PrizeDrawRuleMapper prizeDrawRuleMapper;
    @Autowired
    private ProductInfoMapper productInfoMapper;
    @Autowired
    private SysUserPrizesMapper prizesMapper;
    @Autowired
    private IUserPointsLogService userPointsLogService;
    @Autowired
    private RecordOfWinningAPrizeMapper recordOfWinningAPrizeMapper;
    @Autowired
    private ISysUserService userService;

    /**
     * 查询抽奖规则
     *
     * @param id 抽奖规则主键
     * @return 抽奖规则
     */
    @Override
    public PrizeDrawRuleVo selectPrizeDrawRuleById(Long id) {
        PrizeDrawRuleVo vo = prizeDrawRuleMapper.selectPrizeDrawRuleVoById(id);
        List<PrizeProductInfo> productInfoList = productInfoMapper.selectPrizeDrawRuleProductInfoList(id);
        vo.setProductInfoList(productInfoList);
        return vo;
    }

    /**
     * 查询抽奖规则列表
     *
     * @param prizeDrawRule 抽奖规则
     * @return 抽奖规则
     */
    @Override
    public List<PrizeDrawRule> selectPrizeDrawRuleList(PrizeDrawRule prizeDrawRule) {
        return prizeDrawRuleMapper.selectPrizeDrawRuleList(prizeDrawRule);
    }

    /**
     * 新增抽奖规则
     *
     * @param prizeDrawRule 抽奖规则
     * @return 结果
     */
    @Override
    public int insertPrizeDrawRule(PrizeDrawRule prizeDrawRule) {
        prizeDrawRule.setCreateTime(DateUtils.getNowDate());
        return prizeDrawRuleMapper.insertPrizeDrawRule(prizeDrawRule);
    }

    /**
     * 新增抽奖规则
     *
     * @param prizeDrawRuleVo 抽奖规则
     * @return 结果
     */
    @Override
    public int insertPrizeDrawRule(PrizeDrawRuleVo prizeDrawRuleVo) {
        PrizeDrawRule prizeDrawRule = CommonUtils.convert(prizeDrawRuleVo, PrizeDrawRule.class);
        prizeDrawRule.setCreateTime(DateUtils.getNowDate());
        prizeDrawRuleMapper.insertPrizeDrawRule(prizeDrawRule);
        prizeDrawRuleVo.setId(prizeDrawRule.getId());
        insertRelation(prizeDrawRuleVo);
        return 1;
    }


    /**
     * 修改抽奖规则
     *
     * @param prizeDrawRule 抽奖规则
     * @return 结果
     */
    @Override
    public int updatePrizeDrawRule(PrizeDrawRule prizeDrawRule) {
        prizeDrawRule.setUpdateTime(DateUtils.getNowDate());
        return prizeDrawRuleMapper.updatePrizeDrawRule(prizeDrawRule);
    }

    /**
     * 修改抽奖规则
     *
     * @param prizeDrawRuleVo 抽奖规则
     * @return 结果
     */
    @Override
    public int updatePrizeDrawRule(PrizeDrawRuleVo prizeDrawRuleVo) {
        PrizeDrawRule prizeDrawRule = CommonUtils.convert(prizeDrawRuleVo, PrizeDrawRule.class);
        prizeDrawRule.setUpdateTime(DateUtils.getNowDate());
        prizeDrawRuleMapper.updatePrizeDrawRule(prizeDrawRule);
        prizeDrawRuleMapper.deleteRelation(prizeDrawRuleVo.getId());
        insertRelation(prizeDrawRuleVo);
        return 1;
    }

    /**
     * 批量删除抽奖规则
     *
     * @param ids 需要删除的抽奖规则主键
     * @return 结果
     */
    @Override
    public int deletePrizeDrawRuleByIds(Long[] ids) {
        return prizeDrawRuleMapper.deletePrizeDrawRuleByIds(ids);
    }

    /**
     * 删除抽奖规则信息
     *
     * @param id 抽奖规则主键
     * @return 结果
     */
    @Override
    public int deletePrizeDrawRuleById(Long id) {
        return prizeDrawRuleMapper.deletePrizeDrawRuleById(id);
    }

    public void insertRelation(PrizeDrawRuleVo prizeDrawRuleVo) {
        List<PrizeProductInfo> productInfoList = prizeDrawRuleVo.getProductInfoList();
        if (StringUtils.isNotNull(productInfoList)) {
            List<PrizeDrawRuleProductRelation> list = new ArrayList<PrizeDrawRuleProductRelation>();
            for (PrizeProductInfo productInfo : productInfoList) {
                PrizeDrawRuleProductRelation relation = new PrizeDrawRuleProductRelation();
                relation.setPrizeDrawRuleId(prizeDrawRuleVo.getId());
                relation.setProductId(productInfo.getId());
                relation.setProbabilityOfWinning(productInfo.getProbabilityOfWinning());
                relation.setProductNumber(productInfo.getProductNumber());
                //修改配置产品中的 内定人手机号
                if(StringUtils.isNotEmpty(productInfo.getPredeterminePhone())){
                    relation.setPredeterminePhone(productInfo.getPredeterminePhone());
                }
                list.add(relation);
            }
            if (list.size() > 0) {
                prizeDrawRuleMapper.insertRelation(list);
            }
        }
    }

    @Transactional
    @Override
    public AjaxResult PrizeDraw(Long id, Long userId) {
        //判断抽奖次数是否上限
        String recordCount =  recordOfWinningAPrizeMapper.selectRecordOfWinningAPrizeCount(userId,id);
        PrizeDrawRuleVo ruleVo = prizeDrawRuleMapper.selectPrizeDrawRuleVoById(id);
        try {
            if(!DateUtils.timeCheck(ruleVo.getPrizeDrawStartTime(),ruleVo.getPrizeDrawEndTime())){
                return AjaxResult.error("当前奖池未开放");
            }
        }catch (Exception e){
            return AjaxResult.error("当前奖池未开放");
        }

//        Date start = DateUtils.startOfDay();
//        Date end = DateUtils.endOfDay();
//        List<UserPointsLog> userPointsLogs = userPointsLogService.selectUserPointsLogList(userId, start, end, "3");
        if (Integer.parseInt(recordCount) >= Integer.parseInt(ruleVo.getPrizeDrawNumber())) {
            return AjaxResult.error("已达抽奖上限");
        }

        String prizeDrawType = ruleVo.getPrizeDrawType();
        if(StringUtils.isNotBlank(prizeDrawType)){
            PrizeProductInfo prize = null;
            List<PrizeProductInfo> productInfoListAll = productInfoMapper.selectPrizeDrawRuleProductInfoList(ruleVo.getId());
            List<PrizeProductInfo> productInfoList=productInfoListAll.stream().filter(x->x.getPredeterminePhone()==null).collect(Collectors.toList());
            //判断是否还有库存
            Integer  quantity = productInfoList.stream().mapToInt(item -> Integer.parseInt(item.getProductQuantity())).sum();
            if(quantity<=0){
                return AjaxResult.error("奖品库存不足无法抽取");
            }
            SysUser user = userService.selectUserById(userId);
            if("1".equals(prizeDrawType)){
                //激励抽奖 只消耗次数
                if (!StringUtils.greaterThan(user.getPrizeCount(),"1")) {
                    return AjaxResult.error("抽奖次数不足");
                }
                //抠除抽奖次数
                userService.minusPrizeCount(userId);
                //内定的商品中奖
                List<PrizeProductInfo> appointProductInfoList=productInfoListAll.stream().filter(x->x.getPredeterminePhone()!=null).collect(Collectors.toList());
                //判断指定的大奖商品数量不能为 0
                if(!appointProductInfoList.isEmpty()){
                    for(PrizeProductInfo appointProduct:appointProductInfoList){
                        //如果商品目录中添加的 userid 包含当前的userid就进入
                        if(appointProduct.getPredeterminePhone().contains(userId.toString())){
                            prize = appointProduct;
                            //获得指定商品后操作相关库存与记录
                            operationProduct(userId,prize,id);
                        }
                    }
                }
            }else if("2".equals(prizeDrawType)){
                //积分抽奖只消耗积分
                //抠除积分
                int a = userPointsLogService.losePoints(userId, ruleVo.getExpendPoints(), "3", "积分抽奖");
                if (a == 0) {
                    return AjaxResult.error("积分不足");
                }
                //内定的商品中奖
                List<PrizeProductInfo> appointProductInfoList=productInfoListAll.stream().filter(x->x.getPredeterminePhone()!=null).collect(Collectors.toList());
                //判断指定的大奖商品数量不能为 0
                if(!appointProductInfoList.isEmpty()){
                    for(PrizeProductInfo appointProduct:appointProductInfoList){
                        //如果商品目录中添加的 userid 包含当前的userid就进入
                        if(appointProduct.getPredeterminePhone().contains(userId.toString())){
                            prize = appointProduct;
                            operationProduct(userId,prize,id);
                        }
                    }
                }
            }

            //判断是否获得内定奖品
            if(prize==null){
                //未获得正常抽奖
                int result = new Random().nextInt(100) + 1; // 生成1到100的随机数
                Double sum = Double.parseDouble(ruleVo.getProbabilityOfWinning());
                if (result <= sum) {
                    //中奖
                    double totalProbability =productInfoList.stream().mapToDouble(item -> new BigDecimal(item.getProbabilityOfWinning()).doubleValue()).sum();
                    for (PrizeProductInfo item : productInfoList) {
                        double probability =  new BigDecimal(item.getProbabilityOfWinning()).doubleValue()/totalProbability;
                        item.setProbabilityOfWinning(probability+"");
                    }
                    // 创建一个Random对象
                    Random random = new Random();
                    // 从List中随机选择一个对象
                    prize = selectPrizeProductInfo(productInfoList,random);
                    operationProduct(userId,prize,id);
                }
            }
            if (prize != null) {
                //记录抽奖记录
                recordOfWinningAPrize(userId,prize,user,id);
                return AjaxResult.success(prize);
            } else {
                PrizeProductInfo thanks = productInfoMapper.selectThanks();
                //记录抽奖记录
                recordOfWinningAPrize(userId,thanks,user,id);
                return new AjaxResult(500, "谢谢惠顾", thanks);
            }
        }else {
            return AjaxResult.error("奖池类型配置有误请联系管理员");
        }
    }
    public void recordOfWinningAPrize(Long userId,PrizeProductInfo prize,SysUser user,Long prizeDrawRuleId){
        RecordOfWinningAPrize recordOfWinningAPrize = new RecordOfWinningAPrize();
        recordOfWinningAPrize.setUserId(userId);
        recordOfWinningAPrize.setUserName(user.getNickName());
        recordOfWinningAPrize.setProductId(prize.getId());
        recordOfWinningAPrize.setProductName(prize.getProductName());
        recordOfWinningAPrize.setCreateTime(new Date());
        recordOfWinningAPrize.setPrizeDrawRuleId(prizeDrawRuleId);
        recordOfWinningAPrizeMapper.insertRecordOfWinningAPrize(recordOfWinningAPrize);
    }
    public void operationProduct(Long userId,PrizeProductInfo prize,Long prizeDrawRuleId){
        SysUserPrizes prizes = new SysUserPrizes();
        prizes.setUserId(userId);
        prizes.setProductId(prize.getId());
        prizes.setPrizesStatus("0");
        prizesMapper.insertSysUserPrizes(prizes);
        //商品库存减一
        prize.setProductQuantity(StringUtils.minus(prize.getProductQuantity(), "1"));
        ProductInfo update = CommonUtils.convert(prize,ProductInfo.class);
        productInfoMapper.updateProductInfo(update);
        //奖池商品数减一
        String productNumber = prizeDrawRuleMapper.selectPrizeDrawRuleProductNumber(prizeDrawRuleId,prize.getId());
        productNumber = StringUtils.minus(productNumber, "1");
        prizeDrawRuleMapper.updateProductNumber(prizeDrawRuleId,prize.getId(),productNumber);
    }

    private static PrizeProductInfo selectPrizeProductInfo(List<PrizeProductInfo> items, Random random) {
        double r = random.nextDouble();
        double sum = 0;
        for (PrizeProductInfo item : items) {
            sum += new BigDecimal(item.getProbabilityOfWinning()).doubleValue();
            if (r <= sum) {
                if(Integer.parseInt(item.getProductQuantity())>0){
                    return item;
                }else {
                    return selectPrizeProductInfo(items,random);
                }
            }
        }
        // 理论上不应该到达这里，除非概率计算有误
        throw new IllegalStateException("Unexpected value: no item selected");
    }

    @Override
    public AjaxResult getPrizeDraw() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        List<PrizeDrawRuleVo> prizeDrawRuleVoList = prizeDrawRuleMapper.getPrizeDraw(formatter.format(new Date()));
        if(prizeDrawRuleVoList!=null&&prizeDrawRuleVoList.size()>0){
            return AjaxResult.success(prizeDrawRuleVoList);
        }
        return AjaxResult.error("当前没有抽奖活动,请等待公告");
    }
}
